﻿#ifndef ___PCLIB_S_RANDOM___
#define ___PCLIB_S_RANDOM___


#include "../m_core/m_core.hpp"


/**
*@brief        基于MT19937算法的随机数类
*/
class CPCRandom :CPCNoCopyable
{
public:
    /**
    *@brief     随机生成一个[start,end]范围内的无符号整数。
    *@param     start    [in]    起始值(包括)
    *@param     end      [in]    结束值(包括)
    *@return    结果。
    */
    static unsigned int PCGenRangeAt(unsigned int start = 0, unsigned int end = 0xFFFFFFFF)
    {
        static std::default_random_engine engineUInt((unsigned long)(::time(0)));
        std::uniform_int_distribution<unsigned int> uniformUInt(start, end);
        return uniformUInt(engineUInt);
    }

    /**
    *@brief     随机生成一个[start,end]范围内的浮点数。
    *@param     start    [in]    起始值(包括)
    *@param     end      [in]    结束值(包括)
    *@return    结果。
    */
    static double PCGenDoubleRangeAt(double start, double end)
    {
        static std::default_random_engine engineDouble((unsigned long)(::time(0)));
        std::uniform_real_distribution<double> uniformDouble(start, end);
        return uniformDouble(engineDouble);
    }

    /**
    *@brief     随机生成一个结果的每个字节都在scope范围内的字符串。
    *@param     len          [in]    要生成的字符串长度
    *@param     scope        [in]    范围，如果为空，代表不限制结果的范围(用来生成字节数组)。
    *@return    结果
    */
    static std::string PCGenString(size_t len, const std::string& scope = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
    {
        std::string ret;
        ret.reserve(len + 1);
        static std::default_random_engine engine((unsigned long)(::time(0)));
        if (scope.empty())
        {
            std::uniform_int_distribution<unsigned short> uniform(0x00, 0xFF);
            for (size_t i = 0; i < len; i++)
            {
                ret.push_back( (unsigned char)uniform(engine)  );
            }
        }
        else
        {
            std::uniform_int_distribution<size_t> uniform(0, scope.length() - 1);
            for (size_t i = 0; i < len; i++)
            {
                ret.push_back( scope[uniform(engine)] );
            }
        }
        return ret;
    }

    /**
    *@brief     洗牌算法，打乱数据。
    *@param     src         [in]    要打乱数据。
    *@return    结果
    */
    static std::string PCShuffle(const std::string& src)
    {
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
        //使用c++17新标准的std::shuffle
        std::mt19937 gen(std::random_device{}());
        std::string ret = src;
        std::shuffle(ret.begin(), ret.end(), gen);
        return ret;
#else
        //不支持c++17时继续使用旧标准
        std::string ret = src;
        std::random_shuffle(ret.begin(), ret.end());
        return ret;
#endif
    }
};

#endif    //___PCLIB_S_RANDOM___